package org.bookr.portal.controller;

import junit.framework.Assert;
import org.bookr.engine.model.Book;
import org.bookr.engine.model.Comment;
import org.bookr.engine.model.Group;
import org.bookr.engine.model.Reader;
import org.bookr.engine.service.BookrService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.propertyeditors.CustomCollectionEditor;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ValidationUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.beans.PropertyEditorSupport;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;

/**
 * @author Pawel Tomaszewski
 */
@Controller
public class PortalController implements InitializingBean {
    protected final Logger logger = LoggerFactory.getLogger(PortalController.class);
    protected final String INDEX_VIEW = "portal.index";
    protected final String BOOK_VIEW = "portal.book";
    protected final String REGISTER_VIEW = "portal.register";
    protected final String READER_VIEW = "portal.reader";
    protected final String BOOKS_VIEW = "portal.books";
    protected final String AUTHOR_VIEW = "portal.author";
    protected final String AUTHORS_VIEW = "portal.authors";
    protected final Integer RANDOM_BOOKS_COUNT = 9;
    protected BookrService bookrService;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index(Model model) {
        logger.debug("Loading homepage");
        model.addAttribute("randomBooks", bookrService.fetchRandomBooks(RANDOM_BOOKS_COUNT));
        return INDEX_VIEW;
    }

    @RequestMapping(value = "/book/{id}", method = RequestMethod.GET)
    public String book(@PathVariable String id, Model model) {
        logger.debug("Loading book with id: " + id);
        model.addAttribute("comment", new Comment());
        model.addAttribute("readers", bookrService.listReaders());
        model.addAttribute("books", bookrService.listBooks());
        model.addAttribute("book", bookrService.loadBook(id));
        return BOOK_VIEW;
    }

    @RequestMapping(value = "/book/{id}", method = RequestMethod.POST)
    public String processCreateCommentForm(@PathVariable String id,
                                           @ModelAttribute Comment comment, BindingResult bindingResult,
                                           Model model) {

        ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "title", "portal.webapp.formValidation.emptyField");
        ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "content", "portal.webapp.formValidation.emptyField");

        Book book = bookrService.loadBook(id);
        model.addAttribute("book", book);

        if(bindingResult.hasErrors()) {
            model.addAttribute("status", "sa bledy sztuk: " + bindingResult.getAllErrors().size());
            return BOOK_VIEW;
        } else {
            Date now = new Date();
            comment.setCreatedDate(now);
            comment.setLastUpdateDate(now);

            bookrService.updateComment(comment);
            model.addAttribute("status", "okok");
            return "redirect:/book/" + id;
        }
    }

    @RequestMapping(value = "/books", method = RequestMethod.GET)
    public ModelAndView books() {
        ModelAndView mav = new ModelAndView(BOOKS_VIEW);
        mav.addObject("books", bookrService.listBooks());
        return mav;
    }

    @RequestMapping(value = "/authors", method = RequestMethod.GET)
    public ModelAndView authors() {
        ModelAndView mav = new ModelAndView(AUTHORS_VIEW);
        mav.addObject("authors", bookrService.listAuthors());
        return mav;
    }

    @RequestMapping(value = "/register", method = RequestMethod.GET)
    public ModelAndView generateRegisterForm(@ModelAttribute Reader reader) {
        ModelAndView mav = new ModelAndView(REGISTER_VIEW);
        mav.addObject("groups", bookrService.listGroups());
        return mav;
    }

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public ModelAndView processRegisterForm(@ModelAttribute Reader reader, BindingResult bindingResult ) {
        ModelAndView results = new ModelAndView(REGISTER_VIEW);
        ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "firstName", "portal.webapp.formValidation.emptyField");
        ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "lastName", "portal.webapp.formValidation.emptyField");
        if(bindingResult.hasErrors()) {
            results.addObject("groups", bookrService.listGroups());
        } else {
            Date now = new Date();
            reader.setCreatedDate(now);
            reader.setLastUpdateDate(now);
            bookrService.updateReader(reader);
            results.setViewName(INDEX_VIEW);
        }
        return results;
    }

    @RequestMapping(value = "/author/{id}", method = RequestMethod.GET)
    public ModelAndView author(@PathVariable String id) {
        ModelAndView mav = new ModelAndView(AUTHOR_VIEW);
        mav.addObject("author", bookrService.loadAuthor(id));
        return mav;
    }

    @RequestMapping(value = "/reader/{id}", method = RequestMethod.GET)
    public ModelAndView reader(@PathVariable String id) {
        ModelAndView mav = new ModelAndView(READER_VIEW);
        mav.addObject("reader", bookrService.loadReaderById(id));
        return mav;
    }

    public void setBookrService(BookrService bookrService) {
        this.bookrService = bookrService;
    }

    public void afterPropertiesSet() throws Exception {
        Assert.assertNotNull(bookrService);
    }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss");
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
        binder.registerCustomEditor(Group.class, "group", new PropertyEditorSupport(Group.class) {
            @Override
            public void setAsText(String id) {
                setValue(bookrService.loadGroup(id));
            }
        });
        binder.registerCustomEditor(Book.class, "book", new PropertyEditorSupport(Book.class) {
            @Override
            public void setAsText(String id) {
                setValue(bookrService.loadBook(id));
            }
        });
        binder.registerCustomEditor(Reader.class, "reader", new PropertyEditorSupport(Reader.class) {
            @Override
            public void setAsText(String username) {
                Reader reader = bookrService.loadReaderByUsername(username);
                setValue(reader);
            }
        });
        binder.registerCustomEditor(Set.class, "comments", new CustomCollectionEditor(Set.class) {
            @Override
            public Object convertElement(Object element) {
                if(element instanceof String)
                    return bookrService.loadComment((String) element);
                return null;
            }
        });
    }
}
